package edu.unicen.compilers.polish;
import java.text.DecimalFormat;
import java.util.Vector;


public class ReversePolish {
		
	private Vector<String> vector=new Vector<String>();
	private Vector<Integer> pila=new Vector<Integer>();
	private Vector<Integer> pila_for=new Vector<Integer>();
	private Vector<Integer> unresolvedBi=new Vector<Integer>();
	private int lastComplete=0;
	private boolean isFunction=false;
	private Vector<Function> functions=new Vector<Function>();
	private Vector<String> vars=new Vector<String>();
	public ReversePolish() {
	
	}
	
	public Vector<String> getPolish(){
		return this.vector;
	}
	
	public Vector<Function> getFunctions(){
		return this.functions;
	}
	

	public void startFunction(){
		this.isFunction=true;
		this.functions.add(new Function("F"+this.functions.size()));
	}
	
	public Vector<Integer> getUnresolvedBi(){
		return this.unresolvedBi;
	}
	
	public boolean isFunc(){
		return this.isFunction;
	}
	public void endFunction(){
		this.functions.elementAt(this.functions.size()-1).closeFunction();
		this.isFunction=false;
	}
	public void storeVar(String var){
		if (this.isFunction){
			this.functions.elementAt(this.functions.size()-1).addVar(var);
		}else
			this.vars.add(var);
	}
	
	public void addEntryPoint(String name){
		this.functions.elementAt(this.functions.size()-1).addEntryPoint(name);
	}
	
	public void endEntryPoint(){
		this.functions.elementAt(this.functions.size()-1).endEntryPoint();
	}
	
	public void add(String lexeme){
		if (!this.isFunction)
			vector.add(lexeme);
		else
			this.functions.elementAt(this.functions.size()-1).add(lexeme);
	}
	
	public void resolveJump(){
		if (!this.isFunction){
			DecimalFormat df = new DecimalFormat("######");
			lastComplete=pull();
			vector.set(lastComplete, "_L"+ df.format(this.vector.size()));
		}else{
			this.functions.elementAt(this.functions.size()-1).resolveJump();
		}
	}
	
	public void insertBI(){
		if (!this.isFunction){
			DecimalFormat df = new DecimalFormat("######");
			String a= vector.elementAt(lastComplete);
			
			Double ant= Double.valueOf(a.substring(2)) + 2;
			vector.set(lastComplete, "_L"+df.format(ant));
			vector.add("");
			push();
			vector.add("BI");
		}else{
			this.functions.elementAt(this.functions.size()-1).insertBI();	
		}
	}
	
	public void insertBIFor(){
		if (!this.isFunction){
			DecimalFormat df = new DecimalFormat("######");
			Integer bi=pila_for.remove(pila_for.size()-1)+1;
			//TODO: ADD TO FUNCTIONS
			unresolvedBi.add(bi);
			vector.add("_L"+df.format(bi));
			vector.add("BI");
		}else
			this.functions.elementAt(this.functions.size()-1).insertBIFor();
	}
	public void push(){
		if (!this.isFunction)
			pila.add(vector.size()-1);
		else
			this.functions.elementAt(this.functions.size()-1).push();
		
	}
	public void pushFor(){
		if (!this.isFunction)
			pila_for.add(vector.size()-1);
		else
			this.functions.elementAt(this.functions.size()-1).pushFor();
	}
	
	public Integer pull(){
		if (!this.isFunction)
			return pila.remove(pila.size()-1);
		else
			return this.functions.elementAt(this.functions.size()-1).pull();
	}

	@Override
	public String toString() {
		StringBuffer sb=new StringBuffer();
		sb.append("POLACA GENERAL \n");
		//sb.append(this.vector + " \n");
		for (int i = 0; i < this.vector.size(); i++) {
			sb.append( i +"]   "+this.vector.elementAt(i)+" \n");
		}
		sb.append("FUNCIONES \n");
		for (Function function : this.functions) {
			sb.append(function);	
		}
		return sb.toString(); 
	}

	public boolean existVar(String key) {
		return this.functions.elementAt(this.functions.size()-1).existVar(key);
	}
	
	public String getFunctionPrefix(){
		return this.functions.elementAt(this.functions.size()-1).getPrefix();
	}
	
	public Vector<String> getVars(){
		Vector<String> variables=new Vector<String>(this.vars);
		for (Function function : functions) {
			variables.addAll(function.getVars());
		}
		return variables;
	}
}
